package com.zjpavt.client.extenddevice.voltagecurrent;

import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.zjpavt.client.command.entity.VideoServer;
import com.zjpavt.client.command.offlinecommand.OfflineCommandBean;
import com.zjpavt.client.command.offlinecommand.OfflineCommandManager;
import com.zjpavt.client.enums.ExtendDeviceEnum;
import com.zjpavt.client.event.EventRegisterCenter;
import com.zjpavt.client.extenddevice.AbstractExtendDevice;
import com.zjpavt.client.extenddevice.IExtendDevice;
import com.zjpavt.client.extenddevice.video.IVideoDevice;
import com.zjpavt.client.hal.ExtendDeviceManager;
import com.zjpavt.client.nativemethod.JnIMethod;
import com.zjpavt.client.util.Consts;

import io.netty.util.concurrent.DefaultThreadFactory;
import lombok.extern.slf4j.Slf4j;
/**
 * 视频服务类
 * @author 康其
 *
 */

@Slf4j
public class VideoDevice extends AbstractExtendDevice implements IVideoDevice {

    private static final ScheduledThreadPoolExecutor video = new ScheduledThreadPoolExecutor(1,
            new DefaultThreadFactory("videoDevice"));

    //视频目录校验
    private static final Pattern PROGRAM_CALL = Pattern.compile("<VIDEOLIST(_[\\d]{3}_.{1,}){0,127}>");

    //服务器发送指令判断
    public static final Pattern  videoExpression = Pattern.compile("^([0-1]{12}|[0-1]{24})([0-1]{8})([0-1]{4})([0-1]{4})([0-1]{8})[^>]*$");

    private SimpleDateFormat dateFormat = new SimpleDateFormat(Consts.DATE_FORMAT);
    private SimpleDateFormat timeFormat = new SimpleDateFormat(Consts.TIME_FORMAT);

    //节目数量
    private static final Pattern VIDEO_SUM = Pattern.compile("<VIDEOSUM_[\\d]{1,3}>");

    public VideoDevice(int extendNum) {
        super(extendNum, ExtendDeviceEnum.VIDEO);
        checkVideo();
    }

    @Override
    public boolean checkVideo() {
        VideoServer vs = VideoServer.getInstance();
        checkModeImpl(vs.getMode());
        checkVideoImpl(vs);
        checkSpeedImpl(vs.getSpeed());
        checkBrightImpl(vs.getBright());
        checkVideosummpl();
        checkPlaylistmpl(vs);
        /*checkVideotimeImpl("121");
        checkVideolistsummpl();
        checkPlaylistmpl();
        checkPalytimeImpl("2019", "07", "10", "11", "20", "10", "009");
        checkSystemtimempl();*/
        /*video.schedule(() -> {
        	// 如果检查周期小于30S 则不继续更新等待下次
        	if (System.currentTimeMillis() - getLastQueryTime() < 30 * 1000) {
        	} else {
        		checkVideo();
        	}
        }, 60, TimeUnit.SECONDS);*/
        return false;
    }

    /**
     * 根据节目序号调用节目
     *
     * @param serialNumber
     *            视频序号，三个字节，取值范围000~127
     */

    public void checkVideoImpl(VideoServer vs) {
        if(!"0".equals(vs.getMode()) && !"1".equals(vs.getMode()))
            return;
        String serialNumber = vs.getVideo();

        //因为节目数必须3位数，如果传入进来的位数少了就加
        if(serialNumber != null) {
            int length = serialNumber.length();
            if(length==1) {
                serialNumber = "00"+serialNumber;
            } else if(length==2) {
                serialNumber = "0"+serialNumber;
            }
        }
        //if(times==null || Integer.valueOf(times)==0)times="3600";
        //String str = "<AT_CHECK0_VIDEO_" + serialNumber + "_" + times + ">";
        String str = "<AT_CHECK0_VIDEO_" + serialNumber + ">";
        // 如果查询时间小于10秒 则不更新数据
        String checkVideoInformation = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(),str, 200);
        if (checkVideoInformation == null) {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
            EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.DEVICE_DISCONNECT, dataMap);

        } else {
            //获取成功之后具体业务
            log.debug("checkVideoInformation=====" + checkVideoInformation);
        }

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
        dataMap.put(EventRegisterCenter.EXT_NUM, getExtendNum());

        EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.VIDEO, dataMap);

    }

    /**
     * 速度调节
     *
     * @param serialNumber
     *            速度值，一个字节，范围1~8。
     */
    public void checkSpeedImpl(String serialNumber) {

        // 如果查询时间小于10秒 则不更新数据
        String checkSpeedInformation = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(),
                                       "<AT_CHECK0_SPEED_" + serialNumber + ">", 200);
        if (checkSpeedInformation == null) {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
            EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.DEVICE_DISCONNECT, dataMap);

        } else {
            //获取成功之后具体业务
            log.debug("checkSpeedInformation=====" + checkSpeedInformation);
        }

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
        dataMap.put(EventRegisterCenter.EXT_NUM, getExtendNum());
        EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.VIDEO, dataMap);
    }

    /**
     * 亮度调节
     *
     * @param serialNumber
     *            三个字节，亮度范围000~255
     */
    public void checkBrightImpl(String serialNumber) {
        if(serialNumber != null) {
            int length = serialNumber.length();
            if(length==1) {
                serialNumber = "00"+serialNumber;
            } else if(length==2) {
                serialNumber = "0"+serialNumber;
            }
        }
        // 如果查询时间小于10秒 则不更新数据
        String checkBrightInformation = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(),
                                        "<AT_CHECK0_BRIGHT_" + serialNumber + ">", 200);
        if (checkBrightInformation == null) {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
            EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.DEVICE_DISCONNECT, dataMap);

        } else {
            //获取成功之后具体业务
            log.debug("checkBrightInformation=====" + checkBrightInformation);
        }

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
        dataMap.put(EventRegisterCenter.EXT_NUM, getExtendNum());
        EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.VIDEO, dataMap);
    }

    /**
     * 播放模式
     *
     * @param serialNumber
     *            模式，一个字节，取值范围0~4 模式：0-循环、1-单一、2-定时、3-同步、4-停止
     */
    public void checkModeImpl(String serialNumber) {

        // 如果查询时间小于10秒 则不更新数据
        String checkModeInformation = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(),
                                      "<AT_CHECK0_MODE_" + serialNumber + ">", 200);
        if (checkModeInformation == null) {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
            EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.DEVICE_DISCONNECT, dataMap);

        } else {
            //获取成功之后具体业务
            log.debug("checkModeInformation=====" + checkModeInformation);
        }

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
        dataMap.put(EventRegisterCenter.EXT_NUM, getExtendNum());
        EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.VIDEO, dataMap);
    }

    /**
     * 查询节目数量
     *
     */
    public void checkVideosummpl() {

        // 如果查询时间小于10秒 则不更新数据
        String checkVideosumInformation = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(),
                                          "<AT_CHECK0_VIDEOSUM>", 200);
        if (checkVideosumInformation == null) {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
            EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.DEVICE_DISCONNECT, dataMap);

        } else {
            //获取成功之后具体业务
            log.debug("checkVideosumInformation=====" + checkVideosumInformation);
            Matcher matcher = VIDEO_SUM.matcher(checkVideosumInformation);
            if(matcher.matches()) {
                String videoSum = checkVideosumInformation.substring(10, checkVideosumInformation.length()-1);
                VideoServer vs = VideoServer.getInstance();
                vs.setVideosum(videoSum);
            } else {
                log.debug("查询节目数量失败=====" + checkVideosumInformation);
            }
        }

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
        dataMap.put(EventRegisterCenter.EXT_NUM, getExtendNum());
        EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.VIDEO, dataMap);
    }

    /**
     * 查询单个节目时长(按秒)
     *
     * @param serialNumber
     *            三个字节，视频范围000~127
     */
    public void checkVideotimeImpl(String serialNumber) {

        // 如果查询时间小于10秒 则不更新数据
        String checkVideotimeInformation = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(),
                                           "<AT_CHECK0_VIDEOTIME_" + serialNumber + ">", 200);
        if (checkVideotimeInformation == null) {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
            EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.DEVICE_DISCONNECT, dataMap);

        } else {
            //获取成功之后具体业务
            log.debug("checkVideotimeInformation=====" + checkVideotimeInformation);
        }

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
        dataMap.put(EventRegisterCenter.EXT_NUM, getExtendNum());
        EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.VIDEO, dataMap);
    }

    /**
     * 设置播放时间
     *
     * @param yyyy:
     *            (年)四个字节，mo: (月)两个字节 dd：(日)两个字节
     *            hh：(时)两个字节，mi：(分)两个字节，ss：(秒)两个字节 serialNumber 三个字节，视频范围000~127
     */
    public void checkPalytimeImpl(String yyyy, String mo, String dd, String hh, String mi, String ss,
                                  String serialNumber) {

        String playtimeStr = "<AT_CHECK0_PLAYTIME_" + yyyy + ":" + mo + ":" + dd + "_" + hh + ":" + mi + ":" + ss + "_"+ serialNumber + ">";
        // 如果查询时间小于10秒 则不更新数据 yyyy:mo:dd_hh:mi:ss_nnn
        String checkPalytimeInformation = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(),playtimeStr,200);
        if (checkPalytimeInformation == null) {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
            EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.DEVICE_DISCONNECT, dataMap);

        } else {
            //获取成功之后具体业务
            log.debug("checkPalytimeInformation=====" + checkPalytimeInformation);
        }

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
        dataMap.put(EventRegisterCenter.EXT_NUM, getExtendNum());
        EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.VIDEO, dataMap);
    }

    /**
     * 查询视频列表
     *
     */
    public void checkVideolistsummpl() {

        // 如果查询时间小于10秒 则不更新数据
        String checkVideolistsumInformation = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(),
                                              "<AT_CHECK0_VIDEOLIST>", 200);
        if (checkVideolistsumInformation == null) {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
            EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.DEVICE_DISCONNECT, dataMap);

        } else {
            //获取成功之后具体业务
            log.debug("checkVideolistsumInformation=====" + checkVideolistsumInformation);
        }

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
        dataMap.put(EventRegisterCenter.EXT_NUM, getExtendNum());
        EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.VIDEO, dataMap);
    }

    /**
     * 把指令转换成Play对象
     * @return
     */
    public void transformationPlay(VideoServer vs) {
        List<VideoServer.Play> data = new ArrayList<>();
        try {
            List<OfflineCommandBean> list = OfflineCommandManager.readOfflineCommandListByMonth(new Date());//把这个月的离线指令取出来
            if(list.size()%2 != 0)
                return;//如果list数量不是双数就返回出去
            for(int i=0; i<list.size(); i++) {
                //创建一个新的播放列表对象
                VideoServer.Play play = vs.getPlay();
                OfflineCommandBean ocb1 = list.get(i++);
                OfflineCommandBean ocb2 = list.get(i);
                play.setTimeBegin(ocb1.getDate());
                play.setTimeEnd(ocb2.getDate());
                Matcher matcher = VideoDevice.videoExpression.matcher(ocb1.getCommand());//判断是否是与视频服务器字符串格式一致 如果不一致就不保存
                if(matcher.matches()) {
                    Integer video = Integer.parseInt(matcher.group(2),2);//指定播放节目
                    if(Integer.valueOf(vs.getVideosum())>video) {
                        //因为节目数必须3位数，如果传入进来的位数少了就加
                        String serialNumber = video.toString();
                        if(serialNumber != null) {
                            int length = serialNumber.length();
                            if(length==1) {
                                serialNumber = "00"+serialNumber;
                            } else if(length==2) {
                                serialNumber = "0"+serialNumber;
                            }
                        }
                        play.setVideos(serialNumber);
                        data.add(play);
                    } else {
                        log.debug("VIDEO   ERROR================videoSum:"+vs.getVideosum()+" <= Video:"+video);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if(data.size()<=0)
            return;//如果没有就不处理

        StringBuffer str = new StringBuffer();
        for(VideoServer.Play play : data) {
            String beginDate = dateFormat.format(play.getTimeBegin());
            String beginTime = timeFormat.format(play.getTimeBegin());
            String endTime = timeFormat.format(play.getTimeEnd());
            str.append("_"+beginDate+"_"+beginTime+"_"+play.getVideos()+"_"+endTime);
        }
        vs.setTimingProgramGuides(str.toString());
    }

    /**
     * 设置节目单
     *
     */
    public void checkPlaylistmpl(VideoServer vs) {
        if(!"2".equals(vs.getMode()))
            return;
        StringBuffer str = new StringBuffer("<AT_CHECK0_PLAYLIST");
        str.append(vs.getTimingProgramGuides());
        str.append(">");
        // 如果查询时间小于10秒 则不更新数据
        String checkPlaylistInformation = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(),str.toString(), 200);
        if (checkPlaylistInformation == null) {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
            EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.DEVICE_DISCONNECT, dataMap);

        } else {
            //获取成功之后具体业务
            log.debug("checkPlaylistInformation=====" + checkPlaylistInformation);
        }

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
        dataMap.put(EventRegisterCenter.EXT_NUM, getExtendNum());
        EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.VIDEO, dataMap);
    }

    /**
     * 查询系统时间
     *
     */
    public void checkSystemtimempl() {

        // 如果查询时间小于10秒 则不更新数据
        String checkSystemtimeInformation = JnIMethod.sendMessage2ExtendDeviceByRs485(115200, getExtendNum(),
                                            "<AT_CHECK0_SYSTEMTIME>", 200);
        if (checkSystemtimeInformation == null) {
            Map<String, Object> dataMap = new HashMap<>();
            dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
            EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.DEVICE_DISCONNECT, dataMap);

        } else {
            //获取成功之后具体业务
            log.debug("checkSystemtimeInformation=====" + checkSystemtimeInformation);
        }

        Map<String, Object> dataMap = new HashMap<>();
        dataMap.put(EventRegisterCenter.DEVICE_NAME, ExtendDeviceEnum.VIDEO.getDeviceName());
        dataMap.put(EventRegisterCenter.EXT_NUM, getExtendNum());
        EventRegisterCenter.getInstance().triggerRegisterTask(EventRegisterCenter.VIDEO, dataMap);
    }

}
